package com.itheima.mp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.itheima.mp.domain.dto.PageDTO;
import com.itheima.mp.domain.po.Address;
import com.itheima.mp.domain.po.User;
import com.itheima.mp.domain.query.UserQuery;
import com.itheima.mp.domain.vo.AddressVO;
import com.itheima.mp.domain.vo.UserVO;
import com.itheima.mp.enums.UserStatus;
import com.itheima.mp.mapper.UserMapper;
import com.itheima.mp.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;

    /**
     * 根据id扣减余额
     * @param id
     * @param amount
     */
    @Override
    @Transactional
    public void deduction(Long id, Integer amount) {

        // 1. 查询用户信息
        User user = this.getById(id);

        // 2.判断用户的状态是否正常
        if (user == null || user.getStatus() == UserStatus.FREEZE){
            throw new RuntimeException("用户不存在或已禁用");
        }

        // 3.判断余额是否足够
        if (user.getBalance()< amount){
            throw new RuntimeException("余额不足");
        }

        // 4.扣减
        // 先计算减扣后的结果
        Integer balance = user.getBalance() - amount;

        // 构造条件
        // 如果用户扣减后余额为0的话，那么状态需要改为2（冻结）
        lambdaUpdate()
                .set(User::getBalance,balance)// 更新余额
                .set(balance==0, User::getStatus, UserStatus.FREEZE)// 动态判断，是否更新status
                .eq(User::getId,id)
                .eq(User::getBalance,user.getBalance())// 乐观锁
                .update();


//        List<Long> ids = Arrays.asList(id);
//        LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<User>()
//                .in(User::getId,ids);
//        userMapper.updateBalanceByIds(wrapper,amount);
    }

    /**
     * 根据id查询用户信息，包括地址信息
     * @param id
     * @return
     */
    @Override
    public UserVO getUserAndAddressById(Long id) {
        // 1.根据ID获取用户的信息
        User user = getById(id);
        // 2.获取用户的收货地址
        List<Address> addresses = Db.lambdaQuery(Address.class)
                .eq(Address::getUserId, id)
                .list();
        UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
        if (CollUtil.isNotEmpty(addresses)){
            userVO.setAddresses(BeanUtil.copyToList(addresses, AddressVO.class));
        }
        return userVO;
    }

    /**
     * 批量查询用户信息和收货地址
     * @param ids
     * @return
     */
    @Override
    public List<UserVO> getUserAndAddressByIds(List<Long> ids) {
        // 1.获取用户集合
        List<User> userList = listByIds(ids);
        if (CollUtil.isEmpty(userList)){
            throw new RuntimeException("用户不存在");
        }
        // 2.查询用户的收货地址
        List<Address> addresses = Db.lambdaQuery(Address.class)
                .in(Address::getUserId, ids)
                .list();
        List<AddressVO> addressVOList = BeanUtil.copyToList(addresses, AddressVO.class);
        // 2.1对收货地址进行分组，key是用户ID，value是用户的收货地址集合
        Map<Long, List<AddressVO>> map = new HashMap<>(0);
        if (CollUtil.isNotEmpty(addresses)){
            map = addressVOList.stream().collect(Collectors.groupingBy(AddressVO::getUserId));
        }

        // 3.将收货地址设置到对应的UserVO对象中
        List<UserVO> userVOList = new ArrayList<>();
        for (User user : userList) {
            UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
            userVO.setAddresses(map.get(user.getId()));
            userVOList.add(userVO);
        }

        return userVOList;
    }

    /**
     * 分页查询
     * @param userQuery
     * @return
     */
    @Override
    public PageDTO<UserVO> pageQuery(UserQuery userQuery) {
        // 1.构建条件
//        Page<User> page = Page.of(userQuery.getPageNo(), userQuery.getPageSize());
//        // 1.2.排序条件
//        if (userQuery.getSortBy() != null) {
//            page.addOrder(new OrderItem(userQuery.getSortBy(), userQuery.getIsAsc()));
//        }else{
//            // 默认按照更新时间排序
//            page.addOrder(new OrderItem("update_time", false));
//        }
        Page<User> page = userQuery.toMpPageDefaultSortByCreateTimeDesc();
        // 2.查询
        Page<User> p = lambdaQuery()
                .like(userQuery.getName() != null, User::getUsername, userQuery.getName())
                .eq(userQuery.getStatus() != null, User::getStatus, userQuery.getStatus())
                .ge(userQuery.getMinBalance() != null, User::getBalance, userQuery.getMinBalance())
                .le(userQuery.getMaxBalance() != null, User::getBalance, userQuery.getMaxBalance())
                .page(page);
        // 3.封装
//        PageDTO<UserVO> dto = new PageDTO<>();
//        long total = p.getTotal();
//        long pages = p.getPages();
//        List<User> list = p.getRecords();
//        dto.setPages(pages);
//        dto.setTotal(total);
//        // 如果查到的结果为空则直接返回即可
//        if (CollectionUtils.isEmpty(list)) {
//            dto.setList(Collections.emptyList());
//            return dto;
//        }
//        dto.setList(BeanUtil.copyToList(list, UserVO.class));
//        // 4.返回
//        return dto;
        return PageDTO.of(p, UserVO.class);
    }
}
